/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package pushy.server;

import java.util.HashMap;

/**
 *
 * @author pkoch1
 * 
 * Serverklasse
 * Manager für die Spieler und nutzer, muss immer zuerst gestartet werden!
 * Basiert auf dem Server der ZA-Klassen, d.h. processMessage etc. sind enthalten
 * Startet auf localhost:1234, es darf kein weiterer Server dort laufen
 */
public class Server extends ZAKlassen.Server {

    private HashMap<String, Integer> user = new HashMap<>();
    private HashMap<String, String> ip = new HashMap<>();
    private HashMap<String, Level> level = new HashMap<>();
    
    public Server(int pPortNr) {
        super(pPortNr);
        System.out.println("Server gestartet: Port " + pPortNr);
    }
    
    /**
     * Der Port wird anhand eines Namens ermittelt
     * @param name
     * @return 
     */
    public int getClientPort(String name) {
        if(user.containsKey(name)) return user.get(name);
        return -1;
    }
    
    /**
     * Der Name wird anhand eines Ports ermittelt
     * @param port
     * @return 
     */
    public String getClientName(int port) {
        for(String s : user.keySet()) {
            if(user.get(s).equals(port)) return s;
        }
        return null;
    }
    
    /**
     * Methode für alles
     * Verwaltung durch das festgelegte Protokoll
     * @param pClientIP
     * @param pClientPort
     * @param pMessage 
     */
    @Override
    public void processMessage(String pClientIP, int pClientPort, String pMessage) {
        String pUserName = getClientName(pClientPort);
        System.out.println("<<" + pClientPort + "<<" + pMessage);
        if(pMessage.contains("NEW_USER:")) {    //Registrierung
            System.out.println("Neuer Benutzer");
            if(user.containsKey(pMessage.replace("NEW_USER:", ""))) {
                super.send(pClientIP, pClientPort, "NO");
                System.out.println("bereits registriert");
            }else {
                super.send(pClientIP, pClientPort, "OK");
                user.put(pMessage.replace("NEW_USER:", ""), pClientPort);
                ip.put(pMessage.replace("NEW_USER:", ""), pClientIP);
                System.out.println(pClientPort);
            }
        }else if(pMessage.contains("USER:")) {  //Anmeldung
            System.out.println("Login");
            if(!user.containsKey(pMessage.replace("USER:", ""))) {
                super.send(pClientIP, pClientPort, "NO");
            }else {
                super.send(pClientIP, pClientPort, "OK");
                user.put(pMessage.replace("USER:", ""), pClientPort);
                ip.put(pMessage.replace("USER:", ""), pClientIP);
            }
        }else if(pMessage.contains("REQUEST:")) {   //Spielanfrage
            String m = pMessage.replace("REQUEST:", "");
            if(user.containsKey(m)) {
                super.send(pClientIP, getClientPort(m), "REQUEST:" + getClientName(pClientPort));
            }else {
                super.send(pClientIP, pClientPort, "REFUSED");
            }
        }else if(pMessage.contains("ACCEPTED:")) {  //Spielanfrage akzeptiert
            String user1 = pMessage.replace("ACCEPTED:", "");
            super.send(pClientIP, getClientPort(user1), "ACCEPTED");
            super.send(pClientIP, pClientPort, "ACCEPTED");
            Level l = new Level(user1, getClientName(pClientPort), Level.getDefaultLevel().toString());
            level.put(user1, l);
            level.put(getClientName(pClientPort), l);
            sendLevel(user1);
            sendLevel(getClientName(pClientPort));
            super.send(pClientIP, getClientPort(user1), "COLOR:gelb");
            super.send(pClientIP, pClientPort, "COLOR:grün");
        }else if(pMessage.contains("REFUSED:")) {   //Spielanfrage abgelehnt
            String user1 = pMessage.replace("REFUSED:", "");
            super.send(pClientIP, getClientPort(user1), "REFUSED");
        }else if(pMessage.contains("MOVE:")) {  //Aktion im Spiel
            if(level.containsKey(pUserName) && level.get(pUserName) != null) {
                Pushy pushy = level.get(pUserName).getPushy(pUserName);
                if(pMessage.equals("MOVE:Right")) {
                    pushy.setRichtung(Objekt.RECHTS);
                }else if(pMessage.equals("MOVE:Left")) {
                    pushy.setRichtung(Objekt.LINKS);
                }else if(pMessage.equals("MOVE:Up")) {
                    pushy.setRichtung(Objekt.OBEN);
                }else if(pMessage.equals("MOVE:Down")) {
                    pushy.setRichtung(Objekt.UNTEN);
                }
                pushy.bewegen();
                super.send(pClientIP, user.get(userWithSameLevel(pUserName)), pMessage);
                //super.send(pClientIP, pClientPort, "LEVEL:" + level.get(pUserName).toString());
            }
        }else if(pMessage.equals("LEVEL")) {    //Level wird angefragt
            sendLevel(pUserName);
        }else if(pMessage.equals("LEVEL_ENDED")) {  //Level wurde beendet (vom Client ermittelt)
            if(level.containsKey(pUserName) && level.get(pUserName) != null) level.put(pUserName, null); level.put(userWithSameLevel(pUserName), null);
            //System.out.println(level.toString());
        }else if(pMessage.equals("ONLINE")) {   //Onlineliste wird angefragt
            String s = "";
            for(String key : user.keySet()) {
                if(!user.get(key).equals(pClientPort)) s = s + key + ":";
            }
            if(s.length() > 1) s = s.substring(0, s.length()-1);
            super.send(pClientIP, pClientPort, s);
        }else if(pMessage.equals("CLOSE")) {    //Der Nutzer meldet sich ab
            user.remove(pUserName);
        }else {
            System.out.println("Nachricht: " + pMessage);
            super.send(pClientIP, pClientPort, pMessage);
        }
    }
    
    public static void main(String[] args) {
        Server s = new Server(1234);
    }
    
    @Override
    public void processNewConnection(String pClientIP, int pClientPort) {
        super.processNewConnection(pClientIP, pClientPort);
        System.out.println("Neue Verbindung von " + pClientIP);
    }

    /**
     * Jeweiliges Level wird in Textform an den Spieler gesendet
     * Form: Level:{Siehe Level-Klasse}
     * @param user1 
     */
    private void sendLevel(String user1) {
        super.send(ip.get(user1), getClientPort(user1), "LEVEL:" + level.get(user1).toString());
    }
    
    /**
     * Findet, wenn möglich, den Nutzernamen des Nutzers, welcher das selbe Level mit ihm zusammen spielt
     * @param username
     * @return 
     */
    private String userWithSameLevel(String username) {
        if(username != null && level.containsKey(username)) {
            Level l = level.get(username);
            if(l == null) return null;
            if(username.equals(l.getGreen())) return l.getYellow();
            return l.getGreen();
        }
        return null;
    }
}
